package bb.lanxing.lib.devices.base

import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import bb.lanxing.lib.devices.api.ConnectionListener
import bb.lanxing.lib.devices.api.DeviceManager
import bb.lanxing.lib.devices.api.SmartDevice
import bb.lanxing.lib.devices.core.utils.DeviceHelper
import bb.lanxing.lib.devices.sprint.utils.BleBondUtil
import bb.lanxing.util.Log
import kotlinx.coroutines.sync.Mutex
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat
import no.nordicsemi.android.support.v18.scanner.ScanCallback
import no.nordicsemi.android.support.v18.scanner.ScanResult
import no.nordicsemi.android.support.v18.scanner.ScanSettings
import kotlin.jvm.internal.Intrinsics


class AutoConnector {
    private val TAG = "AutoConnector"
//    private val connectListener: ConnectionListener? = null
    private var isScanning = false
    private val mutex: Mutex = Mutex()

    private val scanner = BluetoothLeScannerCompat.getScanner()
    private val settings: ScanSettings = ScanSettings.Builder().setLegacy(false).setScanMode(0)
        .setUseHardwareBatchingIfSupported(true).build()
    private val tempAutoConnectableDevice = emptyList<SmartDevice>()
    private val tempConnectingDevice = emptyList<SmartDevice>()

    private val broadcastReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            intent?.apply {
                action?.apply {
                    if (this == BluetoothAdapter.ACTION_STATE_CHANGED) {
                        if (intent.getIntExtra(
                                BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF
                            ) == BluetoothAdapter.STATE_ON
                        ) {
                            startOrRefresh()
                        }
                    }
                }
            }
        }
    }

    private val connectListener =
        ConnectionListener { smartDevice, newState, errCode ->
            if (newState == DeviceManager.STATE_DISCONNECTED) {
                startOrRefresh()
            }
        }

    private val scanCallback = object : ScanCallback() {

        override fun onScanResult(callbackType: Int, result: ScanResult) {
            var connectableDeviceWith: SmartDevice?
            val device = result.device
            connectableDeviceWith = getConnectableDeviceWith(device)
            if (connectableDeviceWith != null) {
//                val bluetoothDevice: BluetoothDevice = this.`$bleDevice`
//                val autoConnector: AutoConnector = this.`this$0`
                Log.d(TAG, "onScanning target device, mac: " + device.address + ",name:"
                        + device.name + ", current process: " + android.os.Process.myPid())
                if (!DeviceHelper.isConnected(connectableDeviceWith.address)
                    && !DeviceHelper.isConnecting(connectableDeviceWith.address)) {
                    Log.d(TAG, "onScanning target device, mac: " + device.address + ",name:"
                            + device.name + ", not connect, go ahead to connect")
//                    this.label = 1
                    doConnect(connectableDeviceWith, this)
//                    if (doConnect === coroutine_suspended) {
//                        return coroutine_suspended
//                    }
                } else {
                    Log.d(TAG,"onScanning target device, mac: " + device.address + ",name:"
                            + device.name + ", this device already connected or connecting")
                }
            }

        }

        override fun onScanFailed(errorCode: Int) {
            Log.d(TAG, "onScanFailed $errorCode")
        }
    }

    fun startOrRefresh() {
        Log.d(TAG, "start auto connector...")
        val sb = StringBuilder()
        sb.append("innerStart 开启搜索, 可连接设备:")
        sb.append(tempAutoConnectableDevice.size)
        sb.append(" current process: ")
        sb.append(android.os.Process.myPid())
        Log.d(TAG, sb.toString())
//        if (!isScanning) {
            try {
                if (connectListener != null) {
                    DeviceHelper.registerConnectionStateListener(connectListener)
                }
                scanner.startScan(null, settings, scanCallback)
            } catch (e: Exception) {
                e.printStackTrace()
            }
            isScanning = true
//        }
    }

    fun stop() {
        Log.d(TAG, "stop auto connector...")
        if (isScanning) {
            if (connectListener != null) {
                DeviceHelper.unregisterConnectionStateListener(connectListener)
            }
            scanner.stopScan(scanCallback)
            for (vDevice in tempConnectingDevice) {
                if (!DeviceHelper.isConnected(vDevice.address)) {
                    DeviceHelper.disconnect(vDevice.address)
                }

            }
            //TODO:hu
//            tempConnectingDevice.clear()
            isScanning = false
        }
    }

    fun getConnectableDeviceWith(bluetoothDevice: BluetoothDevice): SmartDevice? {
        var obj: Any?
        val it = tempAutoConnectableDevice.iterator()
        while (true) {
            if (!it.hasNext()) {
                obj = null
                break
            }
            obj = it.next()
            if (Intrinsics.areEqual((obj as SmartDevice?)!!.address, bluetoothDevice.address)) {
                break
            }
        }
        return obj as SmartDevice?
    }

    companion object {
        @Volatile
        private var instance: AutoConnector? = null
        fun getInstance() = instance ?: synchronized(this) { instance ?: AutoConnector() }
    }

    fun doConnect(smartDevice: SmartDevice, continuation: ScanCallback) {
        //TODO:hu
    }

}